﻿
// ———————————————————————–
// <copyright file="LocationPointGenerator.cs" company="The MITRE Corporation">
//    Copyright (c) 2014 The MITRE Corporation. All rights reserved.
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// </copyright>
// ———————————————————————–
/////////////////////////////////////////////////////////////////////////////////////////////////
// LocationPointGenerator.cs:
//
// A generator for good and bad examples of LocationPoint.
//
// Project: NIEMCADTest
// Author:  Lizzie DeYoung - MITRE
/////////////////////////////////////////////////////////////////////////////////////////////////

// Copyright (c) 2014 The MITRE Corporation. All rights reserved.
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-09-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)  
      

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace NIEMCADTest.EventTests
{
  public class LocationPointGenerator : Generator
  {
    public const string CONTENT_SUB = "$content$";
    public const string INNER_NAME_SUB = "$innername$";
    public const string INNER_NAME_END_SUB = "$innername_end$";
    public const string INNER_PREFIX_SUB = "$innerprefix$";
    public const string INNER_NAMESPACE_SUB = "$innernamespace$";

    public const string POINT = "Point gml:id='asdf' srsName='http://metadata.ces.mil/mdr/ns/GSIP/crs/WGS84E_3D'";
    public const string POS = "pos";

    public const string INNER = @"
    <$innerprefix$:$innername$ xmlns:$innerprefix$='$innernamespace$'>
      $content$
    </$innerprefix$:$innername_end$>";

    public const string LOCATION_POINT = @"
    <$prefix$:$name$ xmlns:$prefix$='$namespace$'>
      $content$
    </$prefix$:$name$>";

    public const string WRONG_ELEMENT_NAME = @"
    <$prefix$:asdf xmlns:$prefix$='$namespace$'>
      $content$
    </$prefix$:asdf>";
    
    public static string[] GOOD_POS =
      new string[3] { "0 0 0", "-32 -41 -22", "32 41 22" };

    public static string[] BAD_POS = //TODO: LDY validate out of range?
      new string[3] { "0", "0 0", /* should we validate out of range? "200 0 0", "0 200 0", "-200 0 0", "0 -200 0", */ "0 0 0 0" };

    public static string[] BAD_POINTS =
      new string[3] { "Point", "Point gml:id='asdf'", "Point srsName='http://metadata.ces.mil/mdr/ns/GSIP/crs/WGS84E_3D'" };


    public LocationPointGenerator()
    {
      elementNamespace = "http://example.com/milops/1.1/";
      elementName = "LocationPoint";
      elementPrefix = "mof";
    }

    public List<TestObject> BAD_WrongElementName()
    {
      List<TestObject> list = new List<TestObject>();
      string xml = GetXml(WRONG_ELEMENT_NAME, POINT, POS, GOOD_POS[0]);
      TestObject testObject = GetTestObject(xml);

      list.Add(testObject);

      return list;
    }

    public List<TestObject> BAD_MultipleElements()
    {

      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;

      // repeat point
      xml = GetXml(LOCATION_POINT, POINT, POS, GOOD_POS[0], true, false);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // repeat pos
      xml = GetXml(LOCATION_POINT, POINT, POS, GOOD_POS[0], false, true); 
      testObject = GetTestObject(xml);
      list.Add(testObject);

      return list;
    }

    public List<TestObject> BAD_MissingElements()
    {
      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;

      // no elements
      xml = GetXml(LOCATION_POINT, null, null, null);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // no point element
      xml = GetXml(LOCATION_POINT, null, POS, null);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // no pos element
      xml = GetXml(LOCATION_POINT, POINT, null, null);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      return list;
    }

    public List<TestObject> BAD_BadContent()
    {
      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;

      // bad name point
      xml = GetXml(LOCATION_POINT, "asdf", POS, GOOD_POS[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // bad name point
      foreach (string badPoint in BAD_POINTS)
      {
        xml = GetXml(LOCATION_POINT, badPoint, POS, GOOD_POS[0]);
        testObject = GetTestObject(xml);
        list.Add(testObject);
      }

      // bad name pos
      xml = GetXml(LOCATION_POINT, POINT, "coordinates", GOOD_POS[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // bad pos content
      foreach (string content in BAD_POS)
      {
        xml = GetXml(LOCATION_POINT, POINT, POS, content);
        testObject = GetTestObject(xml);
        list.Add(testObject);
      }

      return list;
    }

    public List<TestObject> GOOD_GoodContent()
    {
      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;

      // good content
      foreach (string content in GOOD_POS)
      {
        xml = GetXml(LOCATION_POINT, POINT, POS, content);
        testObject = GetTestObject(xml);
        list.Add(testObject);
      }

      return list;
    }

    protected override string GetXml(string xml)
    {
      xml = base.GetXml(xml).Replace(
        INNER_PREFIX_SUB, EDXLSharp.EDXLConstants.GMLPrefix).Replace(
        INNER_NAMESPACE_SUB, EDXLSharp.EDXLConstants.GML32Namespace);

      return xml;
    }

    private string GetXml(string xml, string pointElement, string posElement, string position, 
      bool repeatPoint = false, bool repeatPos = false)
    {
      string posXml = "";
      if (posElement != null)
      {
        posXml = GetXml(INNER).Replace(INNER_NAME_END_SUB, posElement).Replace(INNER_NAME_SUB, posElement).Replace(CONTENT_SUB, position);
        if (repeatPos)
        {
          posXml += posXml;
        }
      }

      string pointXml = "";
      if (pointElement != null)
      {
        string endPoint = pointElement.Split(' ').First();
        pointXml = GetXml(INNER).Replace(INNER_NAME_SUB, pointElement).Replace(INNER_NAME_END_SUB, endPoint).Replace(CONTENT_SUB, posXml);
        if (repeatPoint)
        {
          pointXml += pointXml;
        }
      }

      string LocPointXml = GetXml(xml).Replace(CONTENT_SUB, pointXml);

      return LocPointXml;
    }
  }
}
